package org.alis.rpc.common.paap.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.alis.rpc.common.paap.cache.bean.ConfigValue;
import org.alis.rpc.common.paap.constant.Constants;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author lc
 * @version v1.0.0
 * @date 2020/8/28 11:28
 * @className AppconfigClientUtil.class
 */

public final class AppConfigClientUtil {

    private static final Logger logger = LoggerFactory.getLogger(AppConfigClientUtil.class);

    private AppConfigClientUtil() {

    }

    
    private static final String INFO_MESSAGE_TEMPLATE = "请求 URI 地址为：{}";
    /**
     * 获取某个分组下全量配置
     *
     * @param rootUrl
     *            远程配置服务端接口根路径
     * @param groupId
     *            分组ID
     * @return
     */
    public static String getAllConfigs(String rootUrl, String groupId) {
        String uri = rootUrl + String.format(Constants.ALL_API, groupId);
        logger.debug(INFO_MESSAGE_TEMPLATE, uri);
        return sendGet(uri);
    }

    public static String getSysAllConfigs(String rootUrl, String sysId) {
        String uri = rootUrl + String.format(Constants.ALL_API_WITHSYSID, "all", sysId);
        logger.debug(INFO_MESSAGE_TEMPLATE, uri);
        return sendGet(uri);
    }

    /**
     * 根据更新时间获取某个分组下的增量配置
     *
     * @param rootUrl
     *            远程配置服务端接口根路径
     * @param groupId
     *            分组ID
     * @param updateTime
     *            更新时间
     * @return
     */
    public static String getUpdateConfigs(String rootUrl, String groupId, String updateTime) {
        String uri = rootUrl + String.format(Constants.INCREMENT_API, groupId, updateTime);
        logger.debug(INFO_MESSAGE_TEMPLATE, uri);
        return sendGet(uri);
    }

    /**
     * 根据更新时间获取某个系統下所有分組的增量配置
     *
     * @param rootUrl
     *            远程配置服务端接口根路径
     * @param groupId
     *            分组ID
     * @param updateTime
     *            更新时间
     * @return
     */
    public static String getUpdateSysConfigs(String rootUrl, String groupId, String sysid, String updateTime) {
        String uri = rootUrl + String.format(Constants.INCREMENT_SYS_API, groupId, sysid, updateTime);
        logger.debug(INFO_MESSAGE_TEMPLATE, uri);
        return sendGet(uri);
    }

    /**
     * 根据分组ID，配置关键字，单位标识获取单个配置值
     *
     * @param rootUrl
     *            远程配置服务端接口根路径
     * @param groupId
     * @param configKey
     * @param corpId
     * @return
     */
    public static String getConfig(String rootUrl, String groupId, String configKey, String corpId) {
        String uri = rootUrl + String.format(Constants.SINGLE_API, groupId, configKey, corpId);
        logger.debug(INFO_MESSAGE_TEMPLATE, uri);
        return sendGet(uri);
    }

    /**
     * 根据系统标识Id,将传入的配置值迁移到配置服务数据库
     *
     * @param appId
     *
     */
    public static String addConfigValue(String appId, String rootUrl, List<ConfigValue> configvalues) {
        String uri = rootUrl + String.format(Constants.ALL_API, appId);
        List<String> configValueJsonList = getConfigValueJsonList(configvalues);
        return post(uri, JSON.toJSONString( anyList2JSONObjectList(configValueJsonList)));
    }

    private static List<String> getConfigValueJsonList(List<ConfigValue> configvalues) {
        List<String> list = new ArrayList<>();
        for (ConfigValue configvalue : configvalues) {
            list.add(JSON.toJSONString(configvalue));
        }
        return list;
    }

    private static String sendGet(String urlReal) {
        URL realUrl;
        HttpURLConnection connection;
        try {
        urlReal = urlReal.replace(" ", "%20");
        realUrl = new URL(urlReal);
            // 打开和URL之间的连接
            connection = (HttpURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            connection.setConnectTimeout(Constants.REQUEST_TIMEOUT);
            connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
            connection.connect();
        } catch (IOException e) {
            logger.error("构建链接失败,url{},异常堆栈->",urlReal,e);
            return StringUtils.EMPTY;
        }
        StringBuilder result = new StringBuilder();

        try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))){
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            logger.error("配置服务客户端发起http请求异常", e);
        } finally {
            connection.disconnect();
        }
        return result.toString();
    }

    private static String post(String url, String param) {
        // 创建httppost
        HttpPost httppost = new HttpPost(URI.create(url));
        // 创建参数队列
        httppost.setEntity(new StringEntity(param, ContentType.APPLICATION_JSON));
        return executeRequest(httppost);
    }

    private static String executeRequest(HttpRequestBase httpRequest) {
        try(CloseableHttpClient httpclient = HttpClients.createDefault();CloseableHttpResponse response = httpclient.execute(httpRequest)){
            // 获取响应实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toString(entity, "UTF-8");
            }
        }catch (IOException e){
           logger.error("获取数据失败");
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static <T> List<JSONObject> anyList2JSONObjectList(List<T> list) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<JSONObject> jsonObjectList = new ArrayList<JSONObject>();
        for (T t : list) {
            JSONObject jsonObject = null;
            if (t instanceof String) {
                Object object = JSON.parse((String) t);
                if (object instanceof JSONArray) {
                    JSONArray array = (JSONArray) object;
                    for (Object object2 : array) {
                        JSONObject jsonObject2 = JSON.parseObject(object2.toString());
                        jsonObjectList.add(jsonObject2);
                    }
                } else {
                    jsonObject = JSON.parseObject((String) t);
                }
            } else {
                jsonObject = JSON.parseObject(JSON.toJSONString(t));
            }
            if (jsonObject != null) {
                jsonObjectList.add(jsonObject);
            }
        }
        return jsonObjectList;
    }

}
